跳到主要内容

MySQL 使用 Explain 分析优化实例

慢查有什么危害吗?

对于 Linux 操作系统来说,一个进程能打开的 Socket 文件句柄是上限的。即使我们可以动态的调整它的大小,但是也做不到无限大。

通过命令: 查看进程被限制的使用各种资源的量。

ulimit -a 

core file size: 进程崩溃是转储文件大小限制
man loaded memort 最大锁定内存大小
open file 能打开的文件句柄数

大量的慢查占据 MySQL 连接(Linux 操作系统会为每一条连接创建 socket 文件),慢查累积到一定程度还会导致正常的 SQL 得不到连接执行从而变成慢查 SQL。

最终有可能导致 MySQL 的连接全部被耗光而夯死。这就是生产级别的事故了。

如何监控慢查?

查看曾经执行完成的慢查

如果你需要编写一个监控程序探测 MySQL 的慢查询。那完全可以探测分析 MySQL 的 slow.log

如果你还不知道 slow.log 在哪里,可以像下面这样定位到它。slow.log 中记录的就是曾经执行过的慢查信息。

show variables like '%slow%';

注意要开启日志

# 将全局变量设置为ON
set global slow_query_log ='on';

这时你可以尝试使用 select sleep(2); 模拟一条慢查SQL

然后去慢查 sql 中查看具体的慢查详情。

常用sql:

# 查看mysql是否开启了慢查询
show variables like 'slow_query_log';
# 将全局变量设置为ON
set global slow_query_log ='on';
# 查看慢查询日志存储的位置
show variables like 'slow_query_log_file';
# 查看规定的超过多少秒才被算作慢查询记录下来
show variables like 'long_query_time';
show variables like 'long_query%';
# 超过一秒就记录 , 每次修改这个配置都重新建立一次链接
set global long_query_time=1;

查看正在进行的慢查 SQL

我在 A Session 中发起 SQL:select sleep(60);

然后在 B Session 中通过下图的方式可以看到当前正在进行的慢查情况。大家在看的时候注意:Command 的类型为 Query

MySQL也为用户提供了一些原生的慢查工具。比如:查看执行时间最长的10条SQL。

mysqldumpslow -s a1 -n 10  mysql.slow_log

查询优化工具 explain 命令

MySQL 提供了一个 EXPLAIN 命令,它可以对 SELECT 语句进行分析,并输出 SELECT 执行的详细信息,以供开发人员针对性优化。

EXPLAIN 命令用法十分简单,在 SELECT 语句前加上 EXPLAIN 就可以了,例如:

EXPLAIN SELECT * from user_info WHERE id < 300;

EXPLAIN 命令的输出内容大致如下:

mysql> explain select * from user_info where id = 2\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: user_info
partitions: NULL
type: const
possible_keys: PRIMARY(主键)
key: PRIMARY
key_len: 8
ref: const
rows: 1 ---> 表示扫描了多少行
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)

各列的含义如下:

  • id: SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
  • select_type: SELECT 查询的类型.
  • table: 查询的是哪个表
  • partitions: 匹配的分区
  • type: join 类型
  • possible_keys: 此次查询中可能选用的索引
  • key: 此次查询中确切使用到的索引.
  • ref: 哪个字段或常数与 key 一起被使用
  • rows: 显示此查询一共扫描了多少行. 这个是一个估计值.
  • filtered: 表示此查询条件所过滤的数据的百分比
  • extra: 额外的信息

慢查询优化基本步骤

0.先运行看看是否真的很慢,注意设置 SQL_NO_CACHE 否则会先访问缓冲区的数据

-- 查看缓存是否开启
show variables like '%cache%';

-- 临时的会话关闭缓存
set query_cache_type=0;

-- 临时全局修改
set global variables query_cache_type = 0

-- 要永久关闭得去 my.ini 文件修改:
-- query_cache_type=0
-- query_cache_size=0

1.where 条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的 where 都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高

2.explain 查看执行计划,是否与1 预期一致(从锁定记录较少的表开始查询)

3.order by limit 形式的 sql 语句让排序的表优先查

4.了解业务方使用场景

5.加索引时参照建索引的几大原则

6.观察结果,不符合预期继续从0分析

Reference

聊聊什么是慢查、如何监控?如何排查?